"""
Creates the panel bar for the KuplaMail engine
Written By: Daniel Ortiz
"""
import wx, markdown, quopri, base64
import email.quoprimime as quoprimime
import wx.lib.foldpanelbar as fpb
from browser import MailBrowser
from panels import HeaderPanel, AttachmentPanel
from text import RichMailText
from handler.mail import MailHandler
import email.charset

# From: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/466341
def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

class FoldTestPanel(wx.Panel):
    def __init__(self, parent, id, is_text, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=wx.NO_BORDER | wx.TAB_TRAVERSAL):
        
        wx.Panel.__init__(self, parent, id, pos, size, style)
        self.is_text = is_text
        self.CreateControls()
        self.GetSizer().Fit(self)
        self.GetSizer().SetSizeHints(self)
        self.GetSizer().Layout()

        self.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption)


    def OnPressCaption(self, event):
        event.Skip()

    def CreateControls(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        if not self.is_text:
            self.mail_browser = MailBrowser(self)
        else:
            self.mail_browser = RichMailText(self)
        sizer.Add(self.mail_browser, 2, flag = wx.EXPAND)
        self.SetSizer(sizer)
        

class MailPanelBar(fpb.FoldPanelBar):
    def __init__(self, parent, text):
        self.parent = parent
        self.is_text = text
        fpb.FoldPanelBar.__init__(self, parent, style = fpb.FPB_DEFAULT_STYLE | fpb.FPB_VERTICAL | 
                                  wx.FULL_REPAINT_ON_RESIZE)
        self.Variables()
        self.AddPanels()
        self.BindEvents()
        self.ResizeChildren()
        
    def Variables(self):
        """Initiate the class wide variables"""
        self.resize = False
        self.sash_drag = False
        self.initial = True
        self.post_bar = False
        self.first = True
        self.isDraft = False
        self.temporary_collapse = []
        self.mail_hander = MailHandler()
        
    def AddPanels(self):
        """Add the panels of the panel bar"""
        item = self.AddFoldPanel("Header", collapsed = True)
        self.header_panel = HeaderPanel(item)
        self.AddFoldPanelWindow(item, self.header_panel, fpb.FPB_ALIGN_WIDTH)
        item = self.AddFoldPanel("Attachment", collapsed = True)
        self.attachment_panel = AttachmentPanel(item)
        self.AddFoldPanelWindow(item, self.attachment_panel, fpb.FPB_ALIGN_WIDTH)
        item = self.AddFoldPanel("Body", collapsed = True)
        self.browser_panel = FoldTestPanel(item, wx.ID_ANY, self.is_text)
        self.mail_browser = self.browser_panel.mail_browser
        self.AddFoldPanelWindow(item, self.browser_panel, fpb.FPB_ALIGN_WIDTH)
        self.panel_to_key = {self.header_panel: 0,
                             self.attachment_panel : 1,
                             self.mail_browser: 2 }
        
    def BindEvents(self):
        """Bind the relevant class wide events"""
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_IDLE, self.OnIdle)
        self.Bind(fpb.EVT_CAPTIONBAR, self.OnBar)
        
    def OnSize(self, event):
        """Resize the children panel"""
        if not self.resize:
            self.TemporaryCollapse()
        self.resize = True
        event.Skip()
        
    def TemporaryCollapse(self):
        """Temporary collapse of the fold panel bars, so that they are drawn correctly"""
        self.temporary_collapse = []
        for key in range(self.GetCount()):
            item = self.GetFoldPanel(key)
            if item.IsExpanded():
                self.Collapse(item)
                self.temporary_collapse.append(item)
                
    def OnIdle(self, event):
        """Change the size of the children in the panel, when idle"""
        if self.resize and not self.sash_drag:
            self.resize = False
            self.ResizeChildren()
            self.TemporaryExpand()
        if self.post_bar:
            self.post_bar = False
            self.ResizeChildren()
    
    def TemporaryExpand(self):
        """Expand all of the panels that need to be expaned"""
        for p in self.temporary_collapse:
            self.Expand(p)
    
    def BeginSash(self):
        """Begin the sash drag"""   
        if not self.sash_drag:       
            self.sash_drag = True
            
    def EndSash(self):
        """End the sash drag"""
        print 'End'
        self.sash_drag = False
        
    def ResizeChildren(self, expanded_top = False):
        """Resizes the children of the panel"""
        item = self.GetFoldPanel(0)
        item2 = self.GetFoldPanel(1)
        item3 = self.GetFoldPanel(2)
        size = self.GetRect() 
        l = self.GetRect()
        mail = self.browser_panel.GetRect()
        header = self.header_panel.GetRect()
        att = self.attachment_panel.GetRect()
        l = self.GetRect()
        size[0] = mail[0] 
        size[1] = mail[1]
        att[0] = size[0]
        size[3] = l[3] - l[1] - item.GetRect()[3] - item2.GetRect()[3] + size[1]  +  item.GetCaptionLength()
        header[0] = size[0]
        self.browser_panel.SetRect(size)
        self.header_panel.ResizeWithRect(header)
        self.attachment_panel.ResizeWithRect(att)
        self.Refresh()
        
    def OnBar(self, event):
        """Process the bar event"""
        self.post_bar = True
        event.Skip()
        
    def SetDraft(self, isDraft):
        self.isDraft = isDraft
        
    def IsDraft(self):
        return self.isDraft == True
    
    def Display(self, mail, attachments):
        """Display the current piece of mail"""
        self.header_panel.Add(mail)
        self.GetFoldPanel(self.panel_to_key[self.header_panel]).Expand()
        self.ResizeChildren()
        if attachments:
            self.attachment_panel.Add(attachments)
            item = self.panel_to_key[self.attachment_panel]
            self.GetFoldPanel(item).Expand()
        if mail.body:
            body, e_mail = self.GetBody(mail, attachments)
            print len(body), e_mail.encoding, e_mail.charset
            copy_body = body[:]
            if not self.is_text:
                if e_mail.encoding == 'quoted-printable':
                    body = quopri.decodestring(body)
                elif e_mail.encoding == 'base64':
                    body = base64.decodestring(body)
                else:
                    try:
                        body = quopri.decodestring(body)
                    except:
                        body = body
                        
                    try:
                        body = base64.decodestring(body)
                    except:
                        pass
                if not e_mail.encoding or e_mail.encoding.lower() == '7bit':
                    try:
                        body = body.encode('utf-8')
                    except UnicodeDecodeError, e:
                        body = copy_body
                elif mail.charset:
                    body = unicode(body, e_mail.charset)
                else:
                    body = unicode(body, "latin-1")
                body = markdown.markdown(body)
            else:
                body = mail.body
            self.mail_browser.Add(body)
            self.GetFoldPanel(self.panel_to_key[self.mail_browser]).Expand()
        self.TemporaryCollapse()
        self.ResizeChildren()
        self.TemporaryExpand()
        
    def AddressBookHeader(self, text, data):
        """Add the address to the current header"""
        self.header_panel.AppendData(text, data)
        item = self.GetFoldPanel(self.panel_to_key[self.header_panel])
        if not item.IsExpanded():
            item.Expand()
            self.TemporaryCollapse()
            self.ResizeChildren()
            self.TemporaryExpand()
            
    def GetBody(self, mail, attachments):
        """Return the most accurate representation of the current body, and the effective mail"""
        hasAlternative = False
        for a in attachments:
            if a.alternative:
                hasAlternative = True
        if hasAlternative:
            for a in attachments:
                if 'html' in a.content_type:
                    return a.data, a
        return mail.body, mail
        
    def Clear(self):
        """Clear eveything in the panel"""
        self.header_panel.Clear()
        self.attachment_panel.Clear()
        self.mail_browser.Add('')
        self.parent.ClearCurrentName()
        
    def GetMailData(self):
        """Returns the mail data in a dictionary for easy parsing"""
        ret = {}
        mail, mailbox = self.parent.GetCurrentMail()
        ret['Header'] = self.header_panel.GetData()
        ret['Body'] = self.mail_browser.GetData()
        ret['Attachments'] = self.attachment_panel.GetData()
        ret['Mail'] = mail
        ret['Mailbox'] = mailbox
        return ret
    
    def NewAttach(self):
        """Make a new attachment to the attachment panel"""
        self.attachment_panel.NewAttach()
        self.GetFoldPanel(self.panel_to_key[self.attachment_panel]).Expand()
        self.TemporaryCollapse()
        self.ResizeChildren()
        self.TemporaryExpand()
        
    def SaveAttachments(self):
        """Save the current attachments of the attachment panel"""
        self.attachment_panel.SaveAttachments()
        

        

        
            